package com.rudolfheszele.smsselector.controller;

import java.util.Date;
import java.util.LinkedList;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.RelativeLayout.LayoutParams;

import com.rudolfheszele.smsselector.R;
import com.rudolfheszele.smsselector.model.ActionFactory;
import com.rudolfheszele.smsselector.model.LogicalOperationFactory;
import com.rudolfheszele.smsselector.model.RuleFactory;
import com.rudolfheszele.smsselector.model.SmsSelectorRuleSet;
import com.rudolfheszele.smsselector.model.SmsSelectorRuleSetException;
import com.rudolfheszele.smsselector.model.SmsSelectorRuleSet.Action;
import com.rudolfheszele.smsselector.model.SmsSelectorRuleSet.LogicalOperation;
import com.rudolfheszele.smsselector.model.SmsSelectorRuleSet.Rule;
import com.rudolfheszele.smsselector.view.SmsSelectorRuleCreatorActivity;
import com.rudolfheszele.smsselector.view.View;

class SmsSelectorRuleCreatorActivityProgressBarProgressUpdater implements Runnable
{
	public SmsSelectorRuleCreatorActivityProgressBarProgressUpdater(ProgressDialog progressDialog, int progress)
	{
		mProgressDialog = progressDialog;
		mProgress = progress;
	}
	
	@Override
	public void run()
	{
		mProgressDialog.setProgress(mProgress);
	}
	
	private ProgressDialog mProgressDialog;
	private int mProgress;
}

class SmsSelectorRuleCreatorActivityProgressBarFolderUpdater implements Runnable
{
	public SmsSelectorRuleCreatorActivityProgressBarFolderUpdater(ProgressDialog progressDialog, String folder)
	{
		mProgressDialog = progressDialog;
		mFolder = folder;
		mMainController = null;
	}
	
	@Override
	public void run()
	{
		Activity activity = null;
		
		mMainController = ControllerFactoryFactory.getControllerFactory().getController();
		activity = (Activity)mMainController.getView(R.layout.smsselector_rules_creator_activity_layout);
		mProgressDialog.setMessage(activity.getString(R.string.main_activity_text_view_reading_text) + "(from " + mFolder + ")");
	}
	
	private ProgressDialog mProgressDialog;
	private String mFolder;
	private Controller mMainController;
}

public class SmsSelectorRuleCreatorActivityController implements SmsReaderController, OnClickListener
{
	public static final String NEW_RULE = "new_rule";
	public static final String FROM_MESSAGE = "from_message";
	public static final String MESSAGE_TEXT = "message_text";
	public static final String MESSAGE_SENDER = "message_sender";
	public static final String MESSAGE_DATE = "message_date";
	public static final String RULE_NAME = "message_date";
	
	public SmsSelectorRuleCreatorActivityController(Activity activity)
	{	
		mCreatorActivity = (SmsSelectorRuleCreatorActivity)activity;
		mMainController = (SmsSelectorMainController)ControllerFactoryFactory.getControllerFactory().getController();
		mIsEditingRule = false;
		mProgressDialog = null;
	}
	@Override
	public boolean buildMenu(View view, Object menu, Object clicked)
	{
		MenuInflater inflater = mCreatorActivity.getMenuInflater();
		Menu optionsMenu = (Menu)menu;
		
		inflater.inflate(R.menu.smsselector_rule_creator_activity_options_menu, optionsMenu);
		
		return true;
	}

	@Override
	public View getView(int viewId)
	{
		return mCreatorActivity;
	}
	
	@Override
	public void updateView(View view)
	{
		clearRulesViewerActivity();
		registerRuleCreatorActivity();
	}

	@Override
	public boolean menuClicked(View view, Object menu)
	{
		MenuItem menuItem = (MenuItem)menu;
		
		switch(menuItem.getItemId())
		{
			case R.id.rules_creator_activity_save_options_menu_id:
				saveRuleSet();
				break;
			case R.id.rules_creator_activity_exit_options_menu_id:
				mCreatorActivity.finish();
				break;
		}
		
		return false;
	}

	@Override
	public void registerView(View view)
	{
		mCreatorActivity = (SmsSelectorRuleCreatorActivity)view;
	}

	@Override
	public void updateGui(int viewId, Runnable task)
	{
		mCreatorActivity.runOnUiThread(task);
	}
	
	/**
	 * @see Controller
	 */
	@Override
	public void saveState(int viewId, Object state)
	{
		// TODO Auto-generated method stub	
	}
	
	/**
	 * @see Controller
	 */
	@Override
	public void restoreState(int viewId, Object state)
	{
		// TODO Auto-generated method stub
	}
	
	@Override
	public void onClick(android.view.View view)
	{
		switch(view.getId())
		{
			case R.id.rules_creator_activity_rules_first_plus_button_id:
				onPlusButtonClicked((Button)view);
				break;
		}
	}
	
	@Override
	public void smsReadingStarted(SmsSelectorSmsReaderService smsReaderService)
	{
		mProgressDialog.show();
	}
	
	@Override
	public void reportProgress(ProgressState progressState, Object additionalInfo)
	{
		String directory = null;
		int progress = 0;
		
		switch(progressState)
		{
			case NEW_PROGRESS_STATE:
				progress = ((Integer)additionalInfo).intValue();
				updateGui(0, new SmsSelectorRuleCreatorActivityProgressBarProgressUpdater(mProgressDialog, progress));
				break;
			case DIRECTORY_CHANGED_STATE:
				directory = (String)additionalInfo;
				updateGui(0, new SmsSelectorRuleCreatorActivityProgressBarFolderUpdater(mProgressDialog, directory));
				break;
		}
	}
	
	@Override
	public void smsReadingFinished()
	{
		mProgressDialog.dismiss();
		mProgressDialog = null;
	}
	
	private void registerRuleCreatorActivity()
	{
		Intent intent = mCreatorActivity.getIntent();
		LinearLayout ruleLinearLayout = (LinearLayout)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_linear_layout_id);
		Spinner actionSpinner = null;
		Spinner operationsSpinner = null;
		Spinner rulesSpinner = null;
		Button button = null;
		EditText ruleNameEditText = null;
		EditText actionAdditionalInfoEditText = null;
		
		actionSpinner = (Spinner)mCreatorActivity.findViewById(R.id.rules_creator_activity_action_spinner_id);
		operationsSpinner = (Spinner)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_first_operation_spinner_id);
		rulesSpinner = (Spinner)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_first_rule_spinner_id);
		button = (Button)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_first_plus_button_id);
		actionSpinner.setAdapter(new SmsSelectorRuleCreatorActionSpinnerAdapter());
		operationsSpinner.setAdapter(new SmsSelectorRuleCreatorOperationsSpinnerAdapter());
		rulesSpinner.setAdapter(new SmsSelectorRuleCreatorRulesSpinnerAdapter());
		button.setOnClickListener(this);
		if(intent.getBooleanExtra(NEW_RULE, true) == false)
		{
			// The user is going to edit an already existing rule
			String ruleName = intent.getStringExtra(RULE_NAME);
			SmsSelectorRuleSet ruleSet = mMainController.getRuleSetByName(ruleName);
			
			if(ruleSet == null)
			{
				Toast.makeText(mCreatorActivity, "No rule found: " + ruleName, 5).show();
				
				return;
			}
			mIsEditingRule = true;
			ruleNameEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_rule_name_edit_text_id);
			actionAdditionalInfoEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_action_additional_info_edit_text_id);
			ruleNameEditText.setText(ruleName);
			ruleNameEditText.setEnabled(false);
			actionAdditionalInfoEditText.setText(ruleSet.getAction().getAdditionalInfo());
			actionSpinner.setSelection(ruleSet.getAction().getId().getIntValue());
			for(int i = 0; i < ruleSet.getRules().size(); i++)
			{
				RelativeLayout relativeLayout = (RelativeLayout)ruleLinearLayout.getChildAt(i);
				Spinner spinner = null;
				EditText editText = null;
				Button plusButton = null;
				
				for(int j = 0; j < relativeLayout.getChildCount(); j++)
				{
					android.view.View view = relativeLayout.getChildAt(j);
					
					switch(view.getId())
					{
						case R.id.rules_creator_activity_rules_first_rule_spinner_id:
							spinner = (Spinner)view;
							spinner.setSelection(ruleSet.getRules().get(i).getId().getIntValue());
							break;
						case R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id:
							editText = (EditText)view;
							editText.setText(ruleSet.getRules().get(i).getAddtitionalInfo());
							break;
						case R.id.rules_creator_activity_rules_first_operation_spinner_id:
							spinner = (Spinner)view;
							if(i < ruleSet.getLogicalOperations().size())
								spinner.setSelection(ruleSet.getLogicalOperations().get(i).getId().getIntValue());
							else
								spinner.setSelection(0);
							break;
						case R.id.rules_creator_activity_rules_first_plus_button_id:
							plusButton = (Button)view;
							// Add a new rule if there is more info we have
							if(i < 2)
							{
								RelativeLayout rulesRelativeLayout = getNewRuleGui();
								
								ruleLinearLayout.addView(rulesRelativeLayout);
								plusButton.setText(R.string.rules_creator_activity_rules_first_minus_button_text);
							}
							break;
					}
				}
			}
		}
		else if(intent.getBooleanExtra(FROM_MESSAGE, false) == true)
		{
			// The user is going to create a rule from a message
			String messageText = null;
			String messageSender = null;
			String messageDate = null;
			ruleNameEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_rule_name_edit_text_id);
			actionAdditionalInfoEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_action_additional_info_edit_text_id);
			
			
			messageText = intent.getStringExtra(MESSAGE_TEXT);
			messageSender = intent.getStringExtra(MESSAGE_SENDER);
			messageDate = (new Date(intent.getLongExtra(MESSAGE_DATE, 0))).toString();
			
			ruleNameEditText.setText(messageSender + " rule");
			actionAdditionalInfoEditText.setText(messageSender + " folder");
			actionSpinner.setSelection(0);
			for(int i = 0; i < ruleLinearLayout.getChildCount(); i++)
			{
				RelativeLayout relativeLayout = (RelativeLayout)ruleLinearLayout.getChildAt(i);
				Spinner spinner = null;
				EditText editText = null;
				Button plusButton = null;
				
				for(int j = 0; j < relativeLayout.getChildCount(); j++)
				{
					android.view.View view = relativeLayout.getChildAt(j);
					
					switch(view.getId())
					{
						case R.id.rules_creator_activity_rules_first_rule_spinner_id:
							spinner = (Spinner)view;
							spinner.setSelection(i);
							break;
						case R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id:
							editText = (EditText)view;
							switch(i)
							{
								case 0:
									editText.setText(messageSender);
									break;
								case 1:
									editText.setText(messageText);
									break;
								case 2:
									editText.setText(messageDate);
									break;
							}
							break;
						case R.id.rules_creator_activity_rules_first_operation_spinner_id:
							spinner = (Spinner)view;
							spinner.setSelection(0);
							break;
						case R.id.rules_creator_activity_rules_first_plus_button_id:
							plusButton = (Button)view;
							// Add a new rule if there is more info we have
							if(i < 2)
							{
								RelativeLayout rulesRelativeLayout = getNewRuleGui();
								
								ruleLinearLayout.addView(rulesRelativeLayout);
								plusButton.setText(R.string.rules_creator_activity_rules_first_minus_button_text);
							}
							break;
					}
				}
			}
		}
		// Set every button to minus button expect the first one
		for(int i = 0; i < ruleLinearLayout.getChildCount(); i++)
		{
			Button plusButton = (Button)ruleLinearLayout.getChildAt(i).findViewById(R.id.rules_creator_activity_rules_first_plus_button_id);
			
			if(i == 0)
				plusButton.setText(R.string.rules_creator_activity_rules_first_plus_button_text);
			else
				plusButton.setText(R.string.rules_creator_activity_rules_first_minus_button_text);
			
		}
	}
	
	private void onPlusButtonClicked(Button button)
	{
		
		if(button.getText().equals(mCreatorActivity.getString(R.string.rules_creator_activity_rules_first_plus_button_text)))
		{
			// The user wants to add a new rule
			RelativeLayout relativeLayout = getNewRuleGui();
			LinearLayout linearLayout = (LinearLayout)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_linear_layout_id);
			
			//linearLayout.addView(relativeLayout);
			linearLayout.addView(relativeLayout, 0);
			button.setText(R.string.rules_creator_activity_rules_first_minus_button_text);
		}
		else if((button.getText().equals(mCreatorActivity.getString(R.string.rules_creator_activity_rules_first_minus_button_text))))
		{
			// The user wants to remove a rule
			RelativeLayout relativeLayout = (RelativeLayout)button.getParent();
			LinearLayout linearLayout = (LinearLayout)relativeLayout.getParent();
			
			linearLayout.removeView(relativeLayout);
			button.setText(R.string.rules_creator_activity_rules_first_plus_button_text);
		}
	}
	
	private RelativeLayout getNewRuleGui()
	{
		RelativeLayout relativeLayout = new RelativeLayout(mCreatorActivity);
		Spinner ruleSpinner = new Spinner(mCreatorActivity);
		RelativeLayout.LayoutParams ruleSpinnerLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		EditText ruleAdditionalInfoEditText = new EditText(mCreatorActivity);
		RelativeLayout.LayoutParams ruleEditTextSpinnerLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		Spinner operationsSpinner = new Spinner(mCreatorActivity);
		RelativeLayout.LayoutParams operationsSpinnerLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		Button plusButton = new Button(mCreatorActivity);
		RelativeLayout.LayoutParams buttonLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		android.view.View separatorView = new android.view.View(mCreatorActivity);
		LayoutParams separatorViewLayoutParams = new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, 5);
		
		// Creating the rule spinner
		ruleSpinner.setId(R.id.rules_creator_activity_rules_first_rule_spinner_id);
		ruleSpinnerLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
		ruleSpinner.setLayoutParams(ruleSpinnerLayoutParams);
		ruleSpinner.setAdapter(new SmsSelectorRuleCreatorRulesSpinnerAdapter());
		// Creating the rule additional info 
		ruleAdditionalInfoEditText.setId(R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id);
		ruleAdditionalInfoEditText.setLines(1);
		ruleEditTextSpinnerLayoutParams.addRule(RelativeLayout.BELOW, R.id.rules_creator_activity_rules_first_rule_spinner_id);
		ruleAdditionalInfoEditText.setLayoutParams(ruleEditTextSpinnerLayoutParams);
		// Creating operation spinner
		operationsSpinner.setId(R.id.rules_creator_activity_rules_first_operation_spinner_id);
		operationsSpinnerLayoutParams.addRule(RelativeLayout.BELOW, R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id);
		operationsSpinner.setLayoutParams(operationsSpinnerLayoutParams);
		operationsSpinner.setAdapter(new SmsSelectorRuleCreatorOperationsSpinnerAdapter());
		// Creating the button
		plusButton.setId(R.id.rules_creator_activity_rules_first_plus_button_id);
		plusButton.setOnClickListener(this);
		plusButton.setText(R.string.rules_creator_activity_rules_first_plus_button_text);
		buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		buttonLayoutParams.addRule(RelativeLayout.BELOW, R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id);
		plusButton.setLayoutParams(buttonLayoutParams);
		// Create the separator view
		separatorView.setBackgroundColor(0xFF909090);
		separatorViewLayoutParams.addRule(RelativeLayout.BELOW, R.id.rules_creator_activity_rules_first_plus_button_id);
		separatorView.setLayoutParams(separatorViewLayoutParams);
		// Add views to the layout
		relativeLayout.addView(ruleSpinner);
		relativeLayout.addView(ruleAdditionalInfoEditText);
		relativeLayout.addView(operationsSpinner);
		relativeLayout.addView(plusButton);
		relativeLayout.addView(separatorView);
		
		return relativeLayout;
	}
	
	private void saveRuleSet()
	{ 
		EditText ruleSetNameEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_rule_name_edit_text_id);
		String ruleSetName = ruleSetNameEditText.getText().toString();
		Spinner actionSpinner = (Spinner)mCreatorActivity.findViewById(R.id.rules_creator_activity_action_spinner_id);
		EditText actionAdditionalInfoEditText = (EditText)mCreatorActivity.findViewById(R.id.rules_creator_activity_action_additional_info_edit_text_id);
		TextView actionTextView = (TextView)actionSpinner.getAdapter().getDropDownView(actionSpinner.getSelectedItemPosition(), null, actionSpinner);
		String actionName = actionTextView.getText().toString();
		String actionAdditionalInfo = actionAdditionalInfoEditText.getText().toString();
		LinearLayout ruleLinearLayout = (LinearLayout)mCreatorActivity.findViewById(R.id.rules_creator_activity_rules_linear_layout_id);
		SmsSelectorRuleSet ruleSet = mMainController.getRuleSetByName(ruleSetName);
		LinkedList<Rule> rules = new LinkedList<Rule>();
		LinkedList<LogicalOperation> operations = new LinkedList<LogicalOperation>();
		Action action = ActionFactory.createAction(ActionFactory.getActionId(actionName), actionAdditionalInfo);
		
		if(ruleSet != null)
		{
			// We were editing an existing rule. Delete the old one first
			mMainController.removeRuleSet(ruleSet);
		}
		// Collect the rules from the GUI
		for(int i = 0; i < ruleLinearLayout.getChildCount(); i++)
		{
			RelativeLayout relativeLayout = (RelativeLayout)ruleLinearLayout.getChildAt(i);
			Spinner spinner = null;
			EditText editText = null;
			String ruleName = null;
			String ruleAdditionalInfo = null;
			String operationName = null;
			
			for(int j = 0; j < relativeLayout.getChildCount(); j++)
			{
				android.view.View view = relativeLayout.getChildAt(j);
				
				switch(view.getId())
				{
					case R.id.rules_creator_activity_rules_first_rule_spinner_id:
						spinner = (Spinner)view;
						TextView textView = (TextView)spinner.getAdapter().getDropDownView(spinner.getSelectedItemPosition(), null, spinner);
						ruleName = textView.getText().toString();
						break;
					case R.id.rules_creator_activity_rules_first_rule_additional_info_edit_text_id:
						editText = (EditText)view;
						ruleAdditionalInfo = editText.getText().toString();
						break;
					case R.id.rules_creator_activity_rules_first_operation_spinner_id:
						spinner = (Spinner)view;
						operationName = ((TextView)spinner.getSelectedView()).getText().toString();
						break;
				}
			}
			try
			{
				rules.add(RuleFactory.createRule(RuleFactory.getRuleId(ruleName), ruleAdditionalInfo));
			}
			catch(SmsSelectorRuleSetException exception)
			{
				Toast.makeText(mCreatorActivity, "Invalid rule: " + exception.getMessage(), 5);
				return;
			}
			// In the last element we do not need the operation 
			if(i != ruleLinearLayout.getChildCount() - 1)
				operations.add(LogicalOperationFactory.createOperation(LogicalOperationFactory.getOperationId(operationName)));
		}
		if(mIsEditingRule == true)
		{
			ruleSet.setAction(action);
			ruleSet.setLogicalOperations(operations);
			ruleSet.setRules(rules);
		}
		else
			ruleSet = new SmsSelectorRuleSet(rules, operations, action, ruleSetName);
		mMainController.saveRuleSet(ruleSet);
		refreshRules();
	}
	
	private void refreshRules()
	{
		mMainController.startSmsReaderService(this);
		mProgressDialog = new ProgressDialog(mCreatorActivity);
		mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		mProgressDialog.setMax(100);
		mProgressDialog.setProgress(0);
		mProgressDialog.setMessage("");
		mProgressDialog.setOwnerActivity(mCreatorActivity);
	}
	
	private void clearRulesViewerActivity()
	{
		mCreatorActivity.setContentView(R.layout.smsselector_rules_creator_activity_layout);
	}

	private SmsSelectorRuleCreatorActivity mCreatorActivity;
	private SmsSelectorMainController mMainController;
	private boolean mIsEditingRule;
	private ProgressDialog mProgressDialog;
}
